import { _decorator, IVec2, Sprite, UITransform, Node, tween, Vec3 } from 'cc';
import DataManager from '../../Runtime/DataManager';
import { IActor, InputTypeEnum, GSyncDelay, StateTypeEnum, toFixed, EntityTypeEnum } from '../../Common';
import { EntityManager } from '../../Base/EntityManager';
import { ActorStateMachine } from './ActorStateMachine';
import { createUINode } from '../../Utils';
import { EventManager } from '../../Runtime/EventManager';
import { EventTypeEnum, MaterialEnum } from '../../Enum';
import { GameLogic } from '../../Common/Runtime/GameLogic';
import ResourcesManager from '../../Runtime/ResourcesManager';
import { addLabel } from '../../Runtime/MainManager';
import { HPManager } from '../../Common/Runtime/HPManager';
const { ccclass, property } = _decorator;

@ccclass('PlayerManager')
export class ActorManager extends EntityManager {
    id: number = null
    nickName: string = null
    targetPos: IVec2
    direction: IVec2

    body: Node
    async init(state: IActor) {

        const {
            id,
            type,
            nickName,
        } = state

        this.id = id
        this.type = type
        this.nickName = nickName

        this.body = createUINode('body')
        const size = GameLogic.Ins.getEntitySizeByType(type)
        this.body.getComponent(UITransform).setContentSize(size.w, size.h)

        this.body.parent = this.node
        const sprite = this.body.addComponent(Sprite)
        sprite.trim = false
        sprite.sizeMode = Sprite.SizeMode.CUSTOM
        sprite.customMaterial = ResourcesManager.Ins.materialMap.get(MaterialEnum.entityMaterial)

        this.fsm = this.addComponent(ActorStateMachine)
        this.fsm.init(this)

    }

    tick(dt: number) {
        if (!DataManager.Ins.jm || this.id !== DataManager.Ins.myId) {
            return
        }
        const input = DataManager.Ins.jm.input
        if (input?.length()) {
            EventManager.Ins.emit(EventTypeEnum.clientInput, {
                dt: toFixed(dt),
                id: this.id,
                type: InputTypeEnum.actorMove,
                direction: {
                    x: toFixed(input.x),
                    y: toFixed(input.y)
                },
            })
        }
    }

    render(data: IActor) {

        const {
            position: { x, y },
            direction,
        } = data

        if (DataManager.Ins.isSingle) {
            const p = this.node.getPosition()
            if (p.x == x && p.y == y) {
                this.state = StateTypeEnum.idle
            } else {
                this.state = StateTypeEnum.run
            }
            this.node.setPosition(x, y)
        } else {
            if (!this.targetPos) {
                this.node.setPosition(x, y)
                this.state = StateTypeEnum.idle
            } else if (this.targetPos.x !== x || this.targetPos.y !== y) {
                this.state = StateTypeEnum.run
                tween(this.node)
                    .to(GSyncDelay / 1000, { position: new Vec3(x, y) })
                    .delay(0.15)
                    .call(() => {
                        if (this.targetPos.x === x && this.targetPos.y === y) {
                            this.state = StateTypeEnum.idle
                        }
                    })
                    .start()
            }

            this.targetPos = { x, y }
        }
        this.body.setScale(direction.x > 0 ? 1 : -1, 1)

        this.regenerationLabe(data)
    }

    /** 回血飘字 */
    regenerationLabe(data: IActor) {

        const {
            position: { x, y },
            regenerationCD,
            hp
        } = data

        if (regenerationCD <= 0) {
            let regenerationHP = HPManager.Ins.getRegenerationHP()
            if (regenerationHP > 0) {
                addLabel(regenerationHP, EntityTypeEnum.fontGreen, { x, y })
            }
        }
    }
}

